﻿/* Copyright © 2012 Gargol, Gargol at gbot dot org
   Based on CoreDC Copyright 2007 © Johan Pettersson, Fredrik Johansson, Michael Starberg, Christian Epstein.
 
This file is part of ADCCore.

ADCCore is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

ADCCore is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with ADCCore.  If not, see <http://www.gnu.org/licenses/>. */
using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;

namespace ADCCore
{   
    using Classes;

    #region Delegates

    public delegate void DcMessageHandler(DcClient sender, string text);
    public delegate void DcFileTransferHandler(DcClient sender, string cid,string token);
    public delegate void DcEventHandler(DcClient sender);
    public delegate void DcUserMessageHandler(DcClient sender, User user, string text, bool ownMessage);
    public delegate void DcPrivateMessageHandler(DcClient sender, User user, string text);
    public delegate void DcUserHandler(DcClient sender, User user);
    public delegate void DcUserConnectionHandler(DcClient sender, User user, string token, int port,bool ssl);
    public delegate void DcRedirectHandler(DcClient sender, string hubAddress);
    public delegate void DcSearchHandler(DcClient sender, SearchInfo searchInfo);
    public delegate void DcSearchReplyHandler(DcClient sender, SearchReply searchReply);
    public delegate void DcClientInfoHandler(DcClient sender, ClientInfo redirectInfo);
    public delegate void DcUserCommandHandler(DcClient sender, UserCommand userCommand);
    public delegate void DcErrorHandler(DcClient sender, Exception ex);
    public delegate void DcStatusMessageHandler(DcClient sender, int StatusCode, string Message);

    #endregion

    partial class DcClient
    {
        #region Chat

        /// <summary>
        /// Occurs for mainchat messages recieved from the hub.
        /// </summary>
        [Description("Occurs for mainchat messages recieved from the hub.")]
        [Category("Chat")]
        public event DcUserMessageHandler OnMainchatMessage;
        internal bool DoMainchatMessage(User user, string text, bool ownMessage)
        {
            if (System.Threading.Thread.CurrentThread.Name == null)
                System.Threading.Thread.CurrentThread.Name = "DoMainchatMessage";
            if (OnMainchatMessage != null)
            {
                OnMainchatMessage(this, user, text, ownMessage);
                return true;
            }
            return false;
        }

        /// <summary>
        /// Occurs for private messages recieved from other users.
        /// </summary>
        [Description("Occurs for private messages recieved from other users.")]
        [Category("Chat")]
        public event DcPrivateMessageHandler OnPrivateMessageRecieved;
        internal bool DoPrivateMessageRecieved(User user, string text)
        {
            if (System.Threading.Thread.CurrentThread.Name == null)
                System.Threading.Thread.CurrentThread.Name = "DoPrivateMessageRecived";
            if (OnPrivateMessageRecieved != null)
            {
                OnPrivateMessageRecieved(this, user, text);
                return true;
            }
            return false;
        }

        /// <summary>
        /// Occurs for private messages sent to other users.
        /// </summary>
        [Description("Occurs for private messages sent to other users.")]
        [Category("Chat")]
        public event DcPrivateMessageHandler OnPrivateMessageSent;
        internal bool DoPrivateMessageSent(User user, string text)
        {
            if (System.Threading.Thread.CurrentThread.Name == null)
                System.Threading.Thread.CurrentThread.Name = "DoPrivateMessageSent";
            if (OnPrivateMessageSent != null)
            {
                OnPrivateMessageSent(this, user, text);
                return true;
            }
            return false;
        }

        #endregion

        #region Connection

        /// <summary>
        /// Occurs immediatly after calling Connect().
        /// </summary>
        [Description("Occurs immediatly after calling Connect().")]
        [Category("Connection")]
        public event DcEventHandler OnConnecting = delegate { };
        internal void DoConnecting() { OnConnecting(this); }

        /// <summary>
        /// Occurs when accepted into a hub.
        /// </summary>
        [Description("Occurs when accepted into a hub.")]
        [Category("Connection")]
        public event DcEventHandler OnConnected;
        internal void DoConnected()
        {
            if (System.Threading.Thread.CurrentThread.Name == null)
                System.Threading.Thread.CurrentThread.Name = "DoConnected";
            if (OnConnected != null)
            {
                OnConnected(this);
            }
        }

        /// <summary>
        /// Occurs when disconnected from a hub.
        /// </summary>
        [Description("Occurs when disconnected from a hub.")]
        [Category("Connection")]
        public event DcEventHandler OnDisconnected = delegate {};
        internal void DoDisconnected(bool reconnect) { OnDisconnected(this); }

        /// <summary>
        /// Occurs when a Status message is recived.
        /// </summary>
        [Description("Occurs when a Status message is recived.")]
        [Category("Connection")]
        public event DcStatusMessageHandler OnStatusMessageRecived = delegate { };
        internal bool DoStatusMessageRecived(int StatusCode, string Message)
        {
            if (System.Threading.Thread.CurrentThread.Name == null)
                System.Threading.Thread.CurrentThread.Name = "DoStatusMessageRecived";
            if (OnStatusMessageRecived != null)
            {
                OnStatusMessageRecived(this, StatusCode, DcClient.DcDecode(Message));
                return true;
            }
            return false;
        }

        /// <summary>
        /// Occurs when current username is registered and password is incorrect. Not supported by all hubs.
        /// </summary>
        [Description("Occurs when current username is registered and password is incorrect. Not supported by all hubs.")]
        [Category("Connection")]
        public event DcEventHandler OnPasswordRejected = delegate { };
        internal void DoPasswordRejected() { OnPasswordRejected(this); }
        #endregion

        #region Error

        /// <summary>
        /// Occurs when an exception is thrown.
        /// </summary>
        [Description("Occurs when an exception is thrown.")]
        [Category("Error")]
        public event DcErrorHandler OnError;
        internal bool DoError(Exception ex)
        {
            if (System.Threading.Thread.CurrentThread.Name == null)
                System.Threading.Thread.CurrentThread.Name = "DoError";
            if (OnError != null)
            {
                OnError(this, ex);
                return true;
            }
            return false;
        }

        // TODO: If we know it's a bug, shouldn't we fix it instead of sending it to an event?
        [Description("")]
        [Category("Error")]
        public event DcErrorHandler OnBug;
        internal bool DoBug(Exception ex)
        {
            if (System.Threading.Thread.CurrentThread.Name == null)
                System.Threading.Thread.CurrentThread.Name = "DoBug";
            if (OnBug != null)
            {
                OnBug(this, ex);
                return true;
            }
            return false;
        }

        #endregion

        #region Hub

        /// <summary>
        /// Occurs when the topic in the hub changes.
        /// </summary>
        [Description("Occurs when the topic in the hub changes.")]
        [Category("Hub")]
        public event DcMessageHandler OnTopic;
        internal void DoTopic(string text)
        {
            if (System.Threading.Thread.CurrentThread.Name == null)
                System.Threading.Thread.CurrentThread.Name = "DoTopic";
            if (OnTopic != null)
            {
                OnTopic(this, text);
            }
        }

        /// <summary>
        /// Occurs when a (active) client to client connection request is recieved.
        /// </summary>
        [Description("Occurs when a (active) client to client connection request is recieved.")]
        [Category("Hub")]
        public event DcUserConnectionHandler OnClientConnectionRecieved;
        internal void DoClientConnectionRecieved(User user,string token,int port,bool ssl)
        {
            if (System.Threading.Thread.CurrentThread.Name == null)
                System.Threading.Thread.CurrentThread.Name = "DoClientConnectionRecieved";
            if (OnClientConnectionRecieved != null)
            {
                OnClientConnectionRecieved(this, user,token,port,ssl);
            }
        }

        /// <summary>
        /// Occurs when a reversed (passive) client to client connection request is recieved.
        /// </summary>
        [Description("Occurs when a reversed (passive) client to client connection request is recieved.")]
        [Category("Hub")]
        public event DcUserConnectionHandler OnReverseClientConnectionRecieved;
        internal void DoReverseClientConnectionRecieved(User user,string token,int port,bool ssl)
        {
            if (System.Threading.Thread.CurrentThread.Name == null)
                System.Threading.Thread.CurrentThread.Name = "DoReverseClientConnectionRecieved";
            if (OnReverseClientConnectionRecieved != null)
            {
                OnReverseClientConnectionRecieved(this, user, token,port,ssl);
            }
        }

        /// <summary>
        /// Occurs when a UserCommand is recieved from the hub.
        /// </summary>
        [Description("Occurs when a UserCommand is recieved from the hub.")]
        [Category("Hub")]
        public event DcUserCommandHandler OnUserCommand = delegate { };
        internal void DoUserCommand(UserCommand userCommand) { OnUserCommand(this, userCommand); }

        #endregion

        #region Raw
        
        /// <summary>
        /// Occurs for every raw message received from a hub.
        /// </summary>
        [Description("Occurs for every raw message received from a hub.")]
        [Category("Raw")]
        public event DcMessageHandler OnMessageReceived;
        internal void DoMessageReceived(string message)
        {
            if (System.Threading.Thread.CurrentThread.Name == null)
                System.Threading.Thread.CurrentThread.Name = "DoMessageReceived";
            if (OnMessageReceived != null)
            {
                OnMessageReceived(this, message);
            }
        }

        /// <summary>
        /// Occurs for every raw message sent to a hub.
        /// </summary>
        [Description("Occurs for every raw message sent to a hub.")]
        [Category("Raw")]
        public event DcMessageHandler OnMessageSent;
        internal bool DoMessageSent(string message)
        {
            if (OnMessageSent != null)
            {
                OnMessageSent(this, message);
                return true;
            }
            if (System.Threading.Thread.CurrentThread.Name == null)
                System.Threading.Thread.CurrentThread.Name = "DoMessageSent";
            return false;
        }

        // TODO: Tracing what? Write description and actual functionality.
        [Description("")]
        [Category("Raw")]
        public event DcMessageHandler OnTrace;
        internal bool DoTrace(string text)
        {
            if (System.Threading.Thread.CurrentThread.Name == null)
                System.Threading.Thread.CurrentThread.Name = "DoTrace";
            if (OnTrace != null)
            {
                OnTrace(this, text);
                return true;
            }
            return false;
        }

        #endregion

        #region Search

        /// <summary>
        /// Occurs when a search is recieved.
        /// </summary>
        [Description("Occurs when a search is recieved.")]
        [Category("Search")]
        public event DcSearchHandler OnSearch;
        internal bool DoSearch(SearchInfo search)
        {
            if (System.Threading.Thread.CurrentThread.Name == null)
                System.Threading.Thread.CurrentThread.Name = "DoSearch";
            if (OnSearch != null)
            {
                OnSearch(this, search);
                return true;
            }
            return false;
        }

        /// <summary>
        /// Occurs when a searchreply is recieved.
        /// </summary>
        [Description("Occurs when a searchreply is recieved.")]
        [Category("Search")]
        public event DcSearchReplyHandler OnSearchReply;
        internal bool DoSearchReply(SearchReply sr)
        {
            if (System.Threading.Thread.CurrentThread.Name == null)
                System.Threading.Thread.CurrentThread.Name = "DoSearchReply";
            if (OnSearchReply != null)
            {
                OnSearchReply(this, sr);
                return true;
            }
            return false;
        }

        #endregion
        
        #region Trauma

        /// <summary>
        /// Occurs when a redirect request is recieved.
        /// </summary>
        [Description("Occurs when a redirect request is recieved.")]
        [Category("Trauma")]
        public event DcRedirectHandler OnRedirected;
        internal void DoRedirected(string hubAddress)
        {
            if (System.Threading.Thread.CurrentThread.Name == null)
                System.Threading.Thread.CurrentThread.Name = "DoRedirected";
            if (OnRedirected != null)
            {
                OnRedirected(this, hubAddress);
            }
        }

        //[Description("")]
        //[Category("Trauma")]
        //public event DcEventHandler OnKicked;
        
        //[Description("")]
        //[Category("Trauma")]
        //public event DcEventHandler OnDropped;

        #endregion

        #region "FileTransfer"

        /// <summary>
        /// Occurs when a ClientToClient connection is set up.
        /// </summary>
        [Description("Occurs when a ClientToClient connection is set up.")]
        [Category("FileTransfer")]
        public event DcFileTransferHandler OnCtCConnected;
        internal void DoCtCConnected(string cid, string token)
        {
            if (System.Threading.Thread.CurrentThread.Name == null)
                System.Threading.Thread.CurrentThread.Name = "DoCtCConnected";
            if (OnCtCConnected != null)
            {
                OnCtCConnected(this,cid,token);
            }
        }
        #endregion

        /// Users is verified
        #region User

        /// <summary>
        /// Occurs when a new user enters the hub.
        /// </summary>
        [Description("Occurs when a new user enters the hub.")]
        [Category("User")]
        public event DcUserHandler OnJoin;
        internal void DoJoin(User user)
        {
            if (System.Threading.Thread.CurrentThread.Name == null)
                System.Threading.Thread.CurrentThread.Name = "DoJoin";
            if (OnJoin != null)
            {
                OnJoin(this, user);
            }
        }

        /// <summary>
        /// Occurs when an existing user updates his client data.
        /// </summary>
        [Description("Occurs when an existing user updates his client data.")]
        [Category("User")]
        public event DcUserHandler OnUserChanged;
        internal void DoUserChanged(User user)
        {
            if (System.Threading.Thread.CurrentThread.Name == null)
                System.Threading.Thread.CurrentThread.Name = "DoUserChanged";
            if (OnUserChanged != null)
            {
                OnUserChanged(this, user);
            }
        }

        /// <summary>
        /// Occurs when a user exits the hub.
        /// </summary>
        [Description("Occurs when a user exits the hub.")]
        [Category("User")]
        public event DcUserHandler OnParts;
        internal void DoParts(User user)
        {
            if (System.Threading.Thread.CurrentThread.Name == null)
                System.Threading.Thread.CurrentThread.Name = "DoParts";
            if (OnParts != null)
            {
                OnParts(this, user);
            }
        }

        #endregion

    }
}
